package com.dragon.common.spring.openapi.customizers.openapi;

import com.chris.dev.base.libs.v1.http.params.NoneParam;
import com.chris.dev.base.libs.v1.http.protocols.HttpHeader;
import com.chris.dev.base.libs.v1.http.protocols.HttpRequest;
import com.dragon.common.spring.openapi.SchemaHelper;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.Content;
import io.swagger.v3.oas.models.media.MediaType;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.RequestBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springdoc.core.customizers.OpenApiCustomizer;
import org.springframework.stereotype.Component;

/**
 * 自定义OpenAPI文档
 * 1. 确保HttpRequest结构定义
 * 2. 为所有POST接口添加包装
 * 后端开发不需要显式声明HttpRequest，但是接口文档能够正确显示
 */
@Component
public class HttpRequestOpenApiCustomizer implements OpenApiCustomizer {
    private static final Logger log = LoggerFactory.getLogger(HttpRequestOpenApiCustomizer.class);
    @Override
    public void customise(OpenAPI openApi) {
        log.info("HttpRequestOpenApiCustomizer~~");
        // 1. 确保结构定义
        Components components = openApi.getComponents();
        // 1.1 HttpHeader
        SchemaHelper.addHttpHeaderSchema(components);
        // 1.2 HttpRequest
        SchemaHelper.addHttpRequestSchema(components);
        // 1.3 NoneParam
        SchemaHelper.addNoneParamSchema(components);
        // 1.4 HttpRequestNoneParam
        SchemaHelper.addHttpRequestNoneParamSchema(components);

        // 2. 为所有POST接口添加包装
        openApi.getPaths().forEach((path, item) -> {
            // 只为所有POST接口添加包装
            if (item.getPost() != null) {
                wrapParameters(item.getPost(), openApi);
            }
        });
    }

    private void wrapParameters(Operation operation, OpenAPI openApi) {
        RequestBody requestBody = operation.getRequestBody();
        /// 此处应该有个逻辑，就是在没有参数的情况下，依然要给一个空参数的HttpRequest
        if (requestBody == null) {
            requestBody = new RequestBody();
            //创建HttpRequestNoneParam的Schema
            Schema<HttpRequest<NoneParam>> httpRequestNoneParamSchema = new Schema<>()
                    .$ref("#/components/schemas/HttpRequestNoneParam");
            MediaType mediaType = new MediaType();
            mediaType.setSchema(httpRequestNoneParamSchema);
            requestBody.setContent(new Content().addMediaType("application/json", mediaType));
            operation.setRequestBody(requestBody);
            return;
        }
        // 有参数
        requestBody.getContent().forEach((name, mediaType) -> {
            // 跳过已处理的请求
            Schema schema = mediaType.getSchema();
            String srcSchemaRef = schema.get$ref();
            if (null == srcSchemaRef || srcSchemaRef.contains("HttpRequest")) {
                return;
            }
            // 原有的Schema短名称
            String simpleSchemaName = srcSchemaRef.split("/")[3];
            String newSchemaName = "HttpRequest" + simpleSchemaName;

            // 将HttpRequest和原有的参数引用合并创建一个新的参数Schema
            // 检查是否已存在，不存在要创建
            Schema<?> httpRequestSchema;
            if (openApi.getComponents().getSchemas().containsKey(newSchemaName)) {
                httpRequestSchema = openApi.getComponents().getSchemas().get("#/components/schemas/" + newSchemaName);
            } else {
                httpRequestSchema = new Schema<HttpRequest<NoneParam>>()
                        .name(newSchemaName)
                        .addProperty("header", new Schema<HttpHeader>().$ref("#/components/schemas/HttpHeader"))
                        .addProperty("param", new Schema<>().$ref(srcSchemaRef));

                // 在Schema列表中添加新生成的Schema
                openApi.getComponents().addSchemas(newSchemaName, httpRequestSchema);
            }
            mediaType.getSchema().set$ref("#/components/schemas/" + newSchemaName);
        });
    }
}